package org.stvd.controller.workflow;

import java.util.HashMap;
import java.util.Map;

import javax.validation.Valid;

import org.activiti.engine.IdentityService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.stvd.common.Consts;
import org.stvd.common.DepAndUserHolder;
import org.stvd.common.aspectj.lang.annotation.Log;
import org.stvd.common.aspectj.lang.enums.BusinessType;
import org.stvd.common.security.SecurityUserHolder;
import org.stvd.common.utils.InterfaceResult;
import org.stvd.common.utils.ServiceResult;
import org.stvd.common.workflow.WorkflowConsts;
import org.stvd.controller.BaseController;
import org.stvd.core.util.StringUtil;
import org.stvd.entities.admin.Users;
import org.stvd.entities.workflow.WfIndex;
import org.stvd.service.workflow.ProcessCoreService;
import org.stvd.service.workflow.WfIndexService;
import org.stvd.service.workflow.WfLogsService;

/**
 * @Title ApplyBaseController
 * @Destribution 工作流申请抽象类
 * @author houzx
 * @date 2020年10月27日
 */
@Controller
public abstract class ApplyBaseController<T> extends BaseController {

    @Autowired
    WfIndexService wfIndexService;
    @Autowired
    WfLogsService wfLogsService;
    @Autowired
    TaskService taskService;
    @Autowired
    RuntimeService runtimeService;
    @Autowired
    IdentityService identityService;
    @Autowired
    private ProcessCoreService processCoreService;

    private String processDefinitionKey = "";

    public void setProcessDefinitionKey(String processDefinitionKey) {
        this.processDefinitionKey = processDefinitionKey;
    }

    /**
     * 加载列表页面所需数据
     */
    protected abstract String loadPageManageData(T entity);

    /**
     * 加载新增页面所需数据
     */
    protected abstract String loadPageAddData(T entity);

    /**
     * 流程启动
     */
    protected abstract ServiceResult<Map<String, Object>> processStarted(WfIndex wfIndex, T entity,
            Map<String, Object> variables);

    /**
     * 流程删除
     */
    protected abstract ServiceResult<Map<String, Object>> processDelete(String processInstanceId);

    /**
     * 流程详情
     */
    protected abstract String processDetail(String processInstanceId);

    /**
     * 流程条件添加
     */
    protected abstract Map<String, Object> conditionAdd(Map<String, Object> variables, T entity);

    @RequestMapping(value = "manage")
    public String onPageManage(@ModelAttribute("entity") T entity) throws Exception {
        String path = loadPageManageData(entity);
        return StringUtil.isEmpty(path) ? "Manage.html" : path;
    }

    /**
     * @Destribution 申请新增
     * @param entity
     * @return
     */
    @GetMapping(value = "add")
    public String onPageAddLoad(@ModelAttribute("entity") T entity) {
        String path = loadPageAddData(entity);
        return StringUtil.isEmpty(path) ? "Add.html" : path;
    }

    @Log(title = "新增审批业务", businessType = BusinessType.INSERT)
    @PostMapping(value = "add")
    @ResponseBody
    public InterfaceResult<Map<String, Object>> onPageAddAction(@Valid @ModelAttribute("entity") T entity,
            BindingResult bindingResult) throws Exception {
        InterfaceResult<Map<String, Object>> result = new InterfaceResult<Map<String, Object>>();
        if (bindingResult.hasErrors()) {
            result.setError(bindingResult.getAllErrors().get(0).getDefaultMessage());
            return result;
        }
        Map<String, Object> variables = new HashMap<String, Object>();
        WfIndex wfIndex = new WfIndex(processDefinitionKey, SecurityUserHolder.getCurrentUserId(),
                SecurityUserHolder.getCurrentMaxAuthDepId());
        ProcessInstance processInstance = null;
        // 用来设置启动流程的人员ID,即变量${applyUserId}
        identityService.setAuthenticatedUserId(wfIndex.getUserId());
        // 启动流程
        variables.put(WorkflowConsts.INDEX_DEPARTMENT_ID, wfIndex.getDepId());
        variables.put(WorkflowConsts.INDEX_USER_ID, wfIndex.getUserId());
        variables.put(WorkflowConsts.INDEX_USER_NAME, SecurityUserHolder.getCurrentUserInfo().getUname());
        conditionAdd(variables, entity);
        processInstance = processCoreService.startInstanceByKey(wfIndex.getProcDefKey(), "", variables);
        wfIndex.setProcInstId(processInstance.getId());
        WfIndex wfIndexNew=wfIndexService.findByProcInstId(processInstance.getId());
        String assignee = "";
        Map<String, Object> dataResult = DepAndUserHolder.getApproveUserInfo(SecurityUserHolder.getCurrentUserId(),
                Consts.GUID);
        if (dataResult != null && dataResult.size() > 0) {
            Users user = (Users) dataResult.get("approveLeader");
            if (user == null) {
                user = (Users) dataResult.get("approveManage");
            }
            if (user != null) {
                assignee = user.getUserId();
            }
        }
        wfIndexNew.setAssignee(assignee);
        wfIndexService.update(wfIndexNew);
        result.transferResult(processStarted(wfIndex, entity, variables));
        return result;
    }

    /**
     * @Destribution 删除审批申请
     * @param processInstanceId
     * @return
     */
    @Log(title = "审批申请删除", businessType = BusinessType.DELETE)
    @PostMapping(value = "del")
    @ResponseBody
    public InterfaceResult<Map<String, Object>> onWorkflowDelete(String processInstanceId) {
        InterfaceResult<Map<String, Object>> result = new InterfaceResult<Map<String, Object>>();
        ServiceResult<Map<String, Object>> serviceResult = processDelete(processInstanceId);
        if (serviceResult.isSuccess()) {
            wfIndexService.delete(processInstanceId);
            processCoreService.deleteProcessInstanceById(processInstanceId, "无原因");
            result.setMsg("删除成功！");
        } else {
            result.setError("删除失败！<br/>失败原因：" + serviceResult.getMessage());
        }
        return result;
    }

    /**
     * @Destribution 审批申请详情
     * @param processInstanceId 流程实例ID
     * @return
     */
    @GetMapping(value = "detail/{processInstanceId}")
    public String detail(@PathVariable String processInstanceId) {
        map.put("processInstanceId", processInstanceId);
        map.put("logList", wfLogsService.findByProcInstId(processInstanceId));
        String path = processDetail(processInstanceId);
        return StringUtil.isEmpty(path) ? "Detail.html" : path;
    }
}
